#include <core/init.h>
#include <autoconf.h>
#include <core/irq.h>
#include <core/io.h>

// #define PWM_FREQUENCY 50.625MHz //depends on PCLK


static __VOLATILE__ ULONG loop_per_usec = 0;

//after loop_per_usec init
void udelay(ULONG n)
{
	__VOLATILE__ ULONG m = n * loop_per_usec;


	while (m-- > 0);
}

//fixme: temporary
static ULONG CalcLoopVal(ULONG InsNum)
{
	__VOLATILE__ ULONG CurVal;
	__VOLATILE__ int index = 0;


	CurVal = GuGetTick();

	while (index++ <= InsNum);

	return GuGetTick() - CurVal;
}

static void SetLoopVal(ULONG InsNum, ULONG val)
{
	if (val)
		loop_per_usec = InsNum / val / 1000;

	if (0 == loop_per_usec)
	{
		loop_per_usec = 1;
		printf("Using default value: loop_per_usec = %d\n",
			loop_per_usec);
	}
}

static int S3cPwmIsr(void *pDev)
{
	GuIncTick();
	// printf("%s() pwm interrupt!\n", __FUNCTION__);

	writel(readl(VA(PWM_BASE + TCNTO(3))), VA(PWM_BASE + TCNTO(3)));

	return IRQ_HANDLED;
}

#ifndef TEST_INS_NUM
#define TEST_INS_NUM 100000
#endif

static __INIT__ int S3c24xxPwmInit(void)
{
	int ret;


	SUBSYS_INFO("Timer init\n");

	writel(0x0, VA(PWM_BASE + TCFG1));

	writel(0x0, VA(PWM_BASE + TCFG0));

	writel(0x1 << 19, VA(PWM_BASE + TCON));

	writel(20, VA(PWM_BASE + TCMPB(3)));

	writel(25333, VA(PWM_BASE + TCNTB(3)));

	writel((0x1 << 17) | readl(VA(PWM_BASE + TCON)), VA(PWM_BASE + TCON));

	writel(0, VA(PWM_BASE + TCMPB(3)));

	writel(25313, VA(PWM_BASE + TCNTB(3)));

	writel((~(0x1 << 17)) & readl(VA(PWM_BASE + TCON)), VA(PWM_BASE + TCON));

	ret = RegisterIsr(13, S3cPwmIsr, NULL);
	if (ret < 0)
	{
		printf("%s(): RegisterIsr() fail!\n", __FUNCTION__);
		return ret;
	}

	writel((1 << 16) | readl(VA(PWM_BASE + TCON)), VA(PWM_BASE + TCON));

	SetLoopVal(TEST_INS_NUM, CalcLoopVal(TEST_INS_NUM));

	return ret;
}

SUBSYS_INIT(S3c24xxPwmInit);

